package com.gxar.quick.ar.server.base.common.utils;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import java.nio.ByteBuffer;
import java.security.SecureRandom;

public class SaltedEncryptionExample {

    public static void main(String[] args) {
        try {
            long originalValue = 123456789L;

            // 生成随机盐值
            byte[] salt = generateSalt();

            // 生成密钥
            SecretKey secretKey = generateSecretKey();

            // 加密
            byte[] encryptedBytes = encrypt(originalValue, salt, secretKey);

            // 解密
            long decryptedValue = decrypt(encryptedBytes, salt, secretKey);

            System.out.println("Original Value: " + originalValue);
            System.out.println("Salt: " + bytesToHex(salt));
            System.out.println("Encrypted Value: " + bytesToHex(encryptedBytes));
            System.out.println("Decrypted Value: " + decryptedValue);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static byte[] generateSalt() {
        SecureRandom random = new SecureRandom();
        byte[] salt = new byte[16]; // 盐值长度为16字节
        random.nextBytes(salt);
        return salt;
    }

    private static SecretKey generateSecretKey() throws Exception {
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
        keyGenerator.init(128); // 使用128位密钥
        return keyGenerator.generateKey();
    }

    private static byte[] encrypt(long value, byte[] salt, SecretKey secretKey) throws Exception {
        // 将 long 数据和盐值合并
        byte[] combinedBytes = concat(toBytes(value), salt);

        // 使用 AES 加密算法进行加密
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(salt));

        return cipher.doFinal(combinedBytes);
    }

    private static long decrypt(byte[] encryptedBytes, byte[] salt, SecretKey secretKey) throws Exception {
        // 使用 AES 解密算法进行解密
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(salt));

        byte[] decryptedBytes = cipher.doFinal(encryptedBytes);

        ByteBuffer buffer = ByteBuffer.wrap(decryptedBytes);
        return buffer.getLong();
    }

    private static byte[] toBytes(long value) {
        byte[] result = new byte[8];
        for (int i = 7; i >= 0; i--) {
            result[i] = (byte) (value & 0xFF);
            value >>= 8;
        }
        return result;
    }

    private static byte[] concat(byte[] array1, byte[] array2) {
        byte[] result = new byte[array1.length + array2.length];
        System.arraycopy(array1, 0, result, 0, array1.length);
        System.arraycopy(array2, 0, result, array1.length, array2.length);
        return result;
    }

    private static String bytesToHex(byte[] bytes) {
        StringBuilder hexString = new StringBuilder();
        for (byte aByte : bytes) {
            hexString.append(String.format("%02X", aByte));
        }
        return hexString.toString();
    }
}
